﻿using System;
using System.Diagnostics;
using Nb.Common.Extensions;
using Ninject.Extensions.Interception;

namespace Nb.Common.Aop
{
    public class ExecuteTimingInterceptor : SimpleInterceptor
    {
        private Stopwatch _stopwatch = new Stopwatch();

        private static int? importantSpan = null;
        ////目前没有证明其线程安全性，仅供可视化方便，不参与计数
        //[ThreadStatic]
        //private static int InvokeLevelCount = 0;

        protected override void BeforeInvoke(IInvocation invocation)
        {
            _stopwatch.Start();

            //InvokeLevelCount++;
            //var nameSpace = invocation.Request.Target.GetType().Namespace;
            //var friendlyName = invocation.Request.Target.GetType().GetFriendlyName();
            //var friendlyNameForMethod = invocation.Request.Method.GetFriendlyNameForMethod();
            //string message = string.Format(">>[{4} {3}]:[{0} : {1} => {2}]\n", nameSpace, friendlyName, friendlyNameForMethod,
            //    "ENTER " + " | " + _stopwatch.GetHashCode() + " | " + invocation.Request.Target.GetHashCode(), InvokeLevelCount);
            //LogMessage(message);
        }

        protected override void AfterInvoke(IInvocation invocation)
        {
            _stopwatch.Stop();

            var nameSpace = invocation.Request.Target.GetType().Namespace;
            var friendlyName = invocation.Request.Target.GetType().GetFriendlyName();
            var friendlyNameForMethod = invocation.Request.Method.GetFriendlyNameForMethod();

            string message = string.Format(">>[{3}]:[{0} : {1} => {2}]\n", nameSpace, friendlyName, friendlyNameForMethod, _stopwatch.Elapsed.TotalMilliseconds);
            //InvokeLevelCount--;
            //bool endOfUnit = InvokeLevelCount == 0;
            LogMessageIfNecessary(_stopwatch.Elapsed, message);
            _stopwatch.Reset();

            //string message = string.Format(">>[{4} {3}]:[{0} : {1} => {2} {5}]\n", nameSpace, friendlyName, friendlyNameForMethod,
            //    "OUTER " + " | " + _stopwatch.GetHashCode() + " | " + invocation.Request.Target.GetHashCode(), InvokeLevelCount, _stopwatch.Elapsed.TotalMilliseconds);
            //LogMessage(message);
            //_stopwatch.Reset();
            //InvokeLevelCount--;
            //if (InvokeLevelCount == 0)
            //{
            //    LogMessage(">>>>>>>>>>>>>>>>>>>>>>>>>> interception unit");
            //}
        }
        
        const char Star = '☆';
        private static void LogMessageIfNecessary(TimeSpan timeSpan, string message, bool endOfUnit = false)
        {
            if (!importantSpan.HasValue)
            {
                importantSpan = NbPerformanceTraceFacade.InterceptionSlowSpan();
            }
            PerformanceTracer.LogMessageIfNecessary(timeSpan, message, "[PerformanceTracer][ExecuteTimingInterceptor]", Star, importantSpan.Value);
            if (endOfUnit)
            {
                LogMessage(">>>>>>>>>>>>>>>>>>>>>>>>>> interception unit");
            }
        }
        private static void LogMessage(string message)
        {
            UtilsLogger.LogMessage("[PerformanceTracer][ExecuteTimingInterceptor]" + message);
        }
    }
}
